#pragma once

#include "../include/PushFramework.h"

#include "ChannelPushInfo.h"

namespace PushFramework{

class BroadcastChannel;
class OutgoingPacket;
class ServerImpl;

class BroadcastManagerImplBase
{
	friend class BroadcastChannel;
public:
	BroadcastManagerImplBase(void);
	~BroadcastManagerImplBase(void);

	void createChannel(WStrKey channelKey, unsigned int maxPacket, bool requireSubscription, unsigned int uPriority, unsigned int uPacketQuota);
	void removeChannel(WStrKey channelKey);

	bool subscribeClient(ClientKey clientKey, WStrKey channelKey);
	bool unsubscribeClient(ClientKey clientKey, WStrKey channelKey);

	void pushPacket(OutgoingPacket* pPacket, WStrKey channelName, WStrKey killKey = "", int objectCategory = 0);
	void removePacket(WStrKey killKey, int objectCategory, WStrKey channelKey);

	OutgoingPacket* getNextPacket(ClientKey client, double& hPacket, std::string& channelKey);

	
	void disposePacket(double hPacket, std::string channelKey, std::string clientKey, bool bSuccess);

	void removeClient(ClientKey clientKey);


	void disposeAllPackets();

	std::string getChannelsNames();

protected:
	virtual void PreEncodeOutgoingPacket(OutgoingPacket* pPacket) = 0;
	virtual void DeleteOutgoingPacket(OutgoingPacket* pPacket) = 0;
	virtual void ActivateSubscribers(std::string channelName) = 0;
	virtual void ReportOnBeforePushPacket(std::string channelName) {};
	virtual void ReportOnAfterPacketIsSent(std::string channelName, std::string subscriberKey) {};


private:
	typedef struct BroadcastInfo 
	{
		ChannelPushInfo* pPushInfo;
		BroadcastChannel* pBroadcastChannel;
	}BroadcastInfo;
	typedef std::map<std::string, BroadcastInfo*> channelMapT;
	channelMapT channelMap;


	ChannelGroupPushInfo* pChainHead;

	ChannelPushInfo* insertChannelIntoOrderedChain(std::string channelName, unsigned int uPriority, unsigned int uPacketQuota);


	typedef std::map<std::string, ClientSink*> sinkMapT;
	sinkMapT sinkMap;
	OutgoingPacket* getPacketFromGroupChain(ChannelPushInfo* pStartAt , ClientKey client, double& hPacket, std::string& channelKey );
};

}